package com.jy.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jy.api.config.WebSocketUrlUtils;
import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.enums.OrderPayChannel;
import com.jy.api.enums.PayTypeEnum;
import com.jy.api.httputil.HttpUtils;
import com.jy.api.httputil.RSASignature;
import com.jy.api.payReq.*;
import com.jy.api.service.CouponInstanceService;
import com.jy.api.service.LeaseProductService;
import com.jy.api.service.PaymentService;
import com.jy.api.util.*;
import com.thoughtworks.xstream.XStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SuiXinFuServiceImpl {
    String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALSudzxTPNFRY8ql\n" +
            "xf2BCgCpfLq7POr3QVMpeXHhYu52toTx3FrRv82zTOiRY/PpiYIrxkpHYsv0ihG8\n" +
            "kV+Zm7xQ02VGhqo9wJaM0Oaw45B0rw8YjX7UhSxOimlB0/rqTV7nMWmMisfBrZPS\n" +
            "LCKPub83vOw1trjH7Ur4gAd+AiL1AgMBAAECgYAIzNaR4Zv8tfIeVKSoDDjof1jL\n" +
            "34LADvrnigWYPloLM00AfKc25TBqXGlKiopLvvwrkuY9h+yP8oEnDAAon9qt5Gwh\n" +
            "RvYZoztTI8k4UQY6O32Wr4Ic+SzKHBFW7YFpp5iKIdniOL1aBrSfxobJRTzu/1ZF\n" +
            "7+/zfLmMVW/hJ1GCoQJBAN29e5h5I4E9LDovRibS64RHbDQfn/TfaKLxuy+qrJuI\n" +
            "FHD7e4bqtMkSv50T7TzgGMOzWwHmiJIi7GBOBEKQGB8CQQDQmPwJ2iZjkvHFxTpY\n" +
            "Iv1Xt6mKimIjhCMzVv8Bc8yfb9GmAkZaWerdxANu9Et0/86IJV/xQXpC3D/hABSe\n" +
            "rjJrAkBpl/dIl79xpxjtqF+G04B2YLDFbZ31tYIVvnm+bE+ATWA2oXuktxZafoQj\n" +
            "ID8kcy832qxnDkpRFTJtdhmPPSFPAkEAxV5K8yN2uTZbDm5rouMQZEPB5fTDoKkx\n" +
            "CS2iQISJsr2BVxrF6E01vbjuKrh5AO3dQ9JhMgtrHAH7au/BktZtmwJBANJWWsj0\n" +
            "17wCumql7m8ZMytPPKNzTZLrihj+LqQGg35AYA9cD++FqEQV/gWzNoOHPJ6XTdOL\n" +
            "xmgv5G+x8u32mns=";
    //随行付公钥
    String sxfPublic = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjo1+KBcvwDSIo+nMYLeOJ19Ju4ii0xH66ZxFd869EWFWk/EJa3xIA2+4qGf/Ic7m7zi/NHuCnfUtUDmUdP0JfaZiYwn+1Ek7tYAOc1+1GxhzcexSJLyJlR2JLMfEM+rZooW4Ei7q3a8jdTWUNoak/bVPXnLEVLrbIguXABERQ0Ze0X9Fs0y/zkQFg8UjxUN88g2CRfMC6LldHm7UBo+d+WlpOYH7u0OTzoLLiP/04N1cfTgjjtqTBI7qkOGxYs6aBZHG1DJ6WdP+5w+ho91sBTVajsCxAaMoExWQM2ipf/1qGdsWmkZScPflBqg7m0olOD87ymAVP/3Tcbvi34bDfwIDAQAB";
    String orgId = "86146578";
    @Autowired
    private PaymentServiceImpl service;
    @Autowired
    private XStream xstream;
    @Autowired
    private AliyunMNSSend aliyunMNSSend;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private PaymentDao paymentDao;
    @Autowired
    private TransactionTemplate transactoinTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RewardDao rewardDao;
    @Autowired
    private StoreDao storeDao;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RedisSyncLocker redisSyncLocker;
    @Autowired
    private AccountBalanceDao accountBalanceDao;
    @Value("${api.gateway.url}")
    private String baseURL;
    @Autowired
    private StorePayDao storePayDao;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private StockOrderShopDao shopDao;
    @Resource
    private CouponInstanceService couponInstanceService;
    @Autowired
    private LeaseProductOrderDao leaseProductOrderDao;
    @Autowired
    private LeaseProductDao leaseProductDao;
    @Autowired
    private WebSocketUrlUtils urlUtils;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private LeaseProductService leaseProductService;

    public AllPayBaseResult suiXinFuPay(Order order, String authCode, Store store, String mchId) throws Exception {
        // 支付结果不确定
        AllPayBaseResult payResult = suiXinFuiMicroPay(order, authCode, mchId, String.valueOf(order.getAmount()));
        log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{},订单内容{}", order.getStoreId(), order.getId(), "随行付支付开始", payResult, order);
        log.info("payResult" + payResult);

        if (payResult.getErrMsg().contains("不能重复")) {
            return payResult;
        }
        if (payResult.isSuccess()) {
            // 支付成功，更新订单状态
            Payment payment = service.createPaymentBySwiftPassResult(payResult, store.getId());
            // TODO: 2018/8/23  订单状态不应该区分是否履行。该平台可以不管理订单履行情况，因为一般都是线下履行
            if (OrderSource.POS == order.getSource()) {
                order.setStatus(OrderStatus.FINISHED);
            } else {
                order.setStatus(OrderStatus.UNFINISHED);
            }
            order.setPaymentTime(payment.getCreateTime());
            order.setPayId(payment.getId());
            order.setChannel(payResult.getTradeType());
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付成功", payResult);
            // 订单与支付信息的更新在同一个事务中
            orderDao.save(order);
            paymentDao.save(payment);
            service.postPaymentSuccess(order, store);
        } else if (payResult.isFailed()) {
            // 支付失败，允许订单再次支付
            order.setStatus(OrderStatus.CANCELED);
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付失败", payResult);
            orderDao.save(order);
        }
        redisTemplate.opsForValue().set(order.getId(), order.getId(), 5, TimeUnit.SECONDS);
        return payResult;
    }


    public AllPayBaseResult suiXinFuPayFrozen(LeaseProductOrder order, String authCode, String mchId,LeaseProduct product) throws Exception {
        // 支付结果不确定
        AllPayBaseResult payResult = suiXinFuiMicroPayFrozen(order, authCode, mchId, String.valueOf(order.getTotalAmount()));
        log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{},订单内容{}", order.getStoreId(), order.getId(), "随行付支付开始", payResult, order);
        log.info("payResult" + payResult);
        if (payResult.getErrMsg().contains("不能重复")) {
            return payResult;
        }
        if (payResult.isSuccess()) {
            boolean inventory = dealLeaseProductInventory(product, order.getNumName(), order);
            if (inventory) {
                if (!order.getSource().equals(OrderSource.POS)) {
                    notifyPOSNewOrderArrivalLease(order);
                    log.info("店铺id{},消息通知时间并且进来{},订单状态{}", order.getStoreId(), new Date(), order);
                    order.setStatus(OrderStatus.UNFINISHED);
                } else {
                    order.setStatus(OrderStatus.FINISHED);
                }
                order.setPayTime(new Date());
                order.setChannel(payResult.getTradeType());
                log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付成功", payResult);
                // 订单与支付信息的更新在同一个事务中
            }
        } else if (payResult.isFailed()) {
            // 支付失败，允许订单再次支付
            order.setStatus(OrderStatus.CANCELED);
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付失败", payResult);
        }
        leaseProductOrderDao.save(order);
        return payResult;
    }

    public AllPayBaseResult suiXinFuiMicroPayFrozen(LeaseProductOrder order, String authCode, String mchId, String amount) throws Exception {
        String url = "https://openapi.tianquetech.com/order/reverseScan";
        AllPayBaseResult allPayBaseResult = new AllPayBaseResult();
        SuiXinFuBasePayReq<JSONObject> req = new SuiXinFuBasePayReq<>();
        req.setOrgId(orgId);
        req.setReqData(dealMicroPayFrozen(order.getOrderNum(), mchId, authCode, amount, order.getProductName()));
        String request = JSONObject.toJSONString(req);
        HashMap reqMap = JSON.parseObject(request, LinkedHashMap.class, Feature.OrderedField);
        //组装加密串
        String signContent = RSASignature.getOrderContent(reqMap);
        System.out.println("拼接后的参数：" + signContent);
        //sign
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);

        String reqStr = JSON.toJSONString(reqMap);
        System.out.println("请求参数:" + reqMap);
        System.out.println("请求参数:" + reqStr);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        System.out.println("请求支付返回结果" + resultJson);
        HashMap<String, Object> result = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);

        if ("0000".equals(result.get("code"))) {
            HashMap<String, Object> micropayResult = JSON.parseObject(result.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (micropayResult.get("bizCode").equals("0000")) {
                allPayBaseResult.setStatus("0");
                allPayBaseResult.setResultCode("0");
                allPayBaseResult.setOutTradeNo(micropayResult.get("ordNo").toString());

                int getAmount = (int) (Double.valueOf(micropayResult.get("totalOffstAmt").toString()) * 100);
                allPayBaseResult.setTotalFee(getAmount);
                allPayBaseResult.setTimeEnd(micropayResult.get("payTime").toString());
                allPayBaseResult.setTradeType(dealPayType(micropayResult.get("payType").toString()));
                System.out.println("支付后的返回结果" + micropayResult);
            } else if (micropayResult.get("bizCode").equals("2002")) {
                allPayBaseResult.setStatus("1");
                allPayBaseResult.setResultCode("1");
                allPayBaseResult.setNeedQuery("Y");
            } else {
                allPayBaseResult.setStatus("1");
                allPayBaseResult.setResultCode("1");
                allPayBaseResult.setNeedQuery("N");
            }
            allPayBaseResult.setErrMsg(micropayResult.get("bizMsg").toString());
        } else {
            allPayBaseResult.setStatus("1");
            allPayBaseResult.setResultCode("1");
            allPayBaseResult.setNeedQuery("N");
            allPayBaseResult.setErrMsg(result.get("msg").toString());
        }
        return allPayBaseResult;
    }

    private void notifyPOSNewOrderArrivalLease(LeaseProductOrder order) {
        try {
            Map<String, String> map = new HashMap<>();
            map.put("orderId", order.getId() + "");
            map.put("storeId", order.getStoreId());
            map.put("type", "LEASE");
            putWs(map);
        } catch (Exception e) {
            log.warn("Fail to send websocket notify to store:{}", order.getStoreId());
        }
    }

    private void putWs(Map<String, String> map) {
        try {
            //发送ws
            String url = urlUtils.getWs();
            OkHttpUtils.post(url, com.alibaba.fastjson.JSONObject.toJSONString(map));
        } catch (Exception ex) {
            log.error(" Invitation code initialization failed msg:{}", ex);
        }

    }

    public AllPayBaseResult suiXinFuiMicroPay(Order order, String authCode, String mchId, String amount) throws Exception {
        String url = "https://openapi.tianquetech.com/order/reverseScan";
        AllPayBaseResult allPayBaseResult = new AllPayBaseResult();
        SuiXinFuBasePayReq<JSONObject> req = new SuiXinFuBasePayReq<>();
        req.setOrgId(orgId);
        req.setReqData(dealMicroPay(order.getPayOrderId(), mchId, authCode, amount, service.getBody(order)));
        String request = JSONObject.toJSONString(req);
        HashMap reqMap = JSON.parseObject(request, LinkedHashMap.class, Feature.OrderedField);
        //组装加密串
        String signContent = RSASignature.getOrderContent(reqMap);
        System.out.println("拼接后的参数：" + signContent);
        //sign
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);

        String reqStr = JSON.toJSONString(reqMap);
        System.out.println("请求参数:" + reqMap);
        System.out.println("请求参数:" + reqStr);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        System.out.println("请求支付返回结果" + resultJson);
        HashMap<String, Object> result = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);

        if ("0000".equals(result.get("code"))) {
            HashMap<String, Object> micropayResult = JSON.parseObject(result.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (micropayResult.get("bizCode").equals("0000")) {
                allPayBaseResult.setStatus("0");
                allPayBaseResult.setResultCode("0");
                allPayBaseResult.setOutTradeNo(micropayResult.get("ordNo").toString());

                int getAmount = (int) (Double.valueOf(micropayResult.get("totalOffstAmt").toString()) * 100);
                allPayBaseResult.setTotalFee(getAmount);
                allPayBaseResult.setTimeEnd(micropayResult.get("payTime").toString());
                allPayBaseResult.setTradeType(dealPayType(micropayResult.get("payType").toString()));
                System.out.println("支付后的返回结果" + micropayResult);
            } else if (micropayResult.get("bizCode").equals("2002")) {
                allPayBaseResult.setStatus("1");
                allPayBaseResult.setResultCode("1");
                allPayBaseResult.setNeedQuery("Y");
            } else {
                allPayBaseResult.setStatus("1");
                allPayBaseResult.setResultCode("1");
                allPayBaseResult.setNeedQuery("N");
            }
            allPayBaseResult.setErrMsg(micropayResult.get("bizMsg").toString());
        } else {
            allPayBaseResult.setStatus("1");
            allPayBaseResult.setResultCode("1");
            allPayBaseResult.setNeedQuery("N");
            allPayBaseResult.setErrMsg(result.get("msg").toString());
        }
        return allPayBaseResult;
    }

    private String dealPayType(String type) {
        String payType = "";
        switch (type) {
            case "WECHAT":
                payType = "pay.wechat.native";
                break;
            case "ALIPAY":
                payType = "pay.alipay.native";
                break;
            case "UNIONPAY":
                payType = "pay.unionpay.micropay";
                break;
        }
        return payType;

    }

    public JSONObject dealMicroPay(String orderId, String mchId, String authCode, String amount, String detail) {
        JSONObject reqData = new JSONObject();
        reqData.put("mno", mchId); //商户编号
        reqData.put("ordNo", orderId); //商户订单号
        reqData.put("authCode", authCode); //授权码
        reqData.put("amt", amount); //订单总金额
        reqData.put("subject", detail); //订单标题
        reqData.put("tradeSource", "01"); //交易来源 01服务商，02收银台，03硬件
        reqData.put("trmIp", "172.16.2.1");
        reqData.put("notifyUrl", baseURL + "/v1/pay/suixinfu/callBack");
        log.info("订单号{},请求参数{}", orderId, reqData);
        return reqData;
    }

    public JSONObject dealMicroPayFrozen(String orderId, String mchId, String authCode, String amount, String detail) {
        JSONObject reqData = new JSONObject();
        reqData.put("mno", mchId); //商户编号
        reqData.put("ordNo", orderId); //商户订单号
        reqData.put("authCode", authCode); //授权码
        reqData.put("amt", amount); //订单总金额
        reqData.put("subject", detail); //订单标题
        reqData.put("tradeSource", "01"); //交易来源 01服务商，02收银台，03硬件
        reqData.put("trmIp", "172.16.2.1");
        reqData.put("ledgerAccountFlag", "07");
        reqData.put("ledgerAccountEffectTime", "30");
        reqData.put("notifyUrl", baseURL + "/v1/pay/lease/suixinfu/callBack");
        log.info("订单号{},请求参数{}", orderId, reqData);
        return reqData;
    }

    public AllPayBaseQueryResult suiXinFuQuery(String orderId, String mchId) throws Exception {
        String url = "https://openapi.tianquetech.com/query/tradeQuery";
        AllPayBaseQueryResult result = new AllPayBaseQueryResult();
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<>();
        reqBean.setOrgId(orgId);
        JSONObject reqData = new JSONObject();
        reqData.put("mno", mchId); //商户编号
        //下面三个至少传一个
        reqData.put("ordNo", orderId); //商户订单号
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        //此处不要改变reqData里面值的顺序用LinkedHashMap
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        //组装加密串
        String signContent = RSASignature.getOrderContent(reqMap);
        System.out.println("拼接后的参数：" + signContent);
        //sign
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);

        String reqStr = JSON.toJSONString(reqMap);
        System.out.println("请求参数:" + reqMap);
        System.out.println("请求参数:" + reqStr);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        System.out.println("返回参数" + resultJson);
        HashMap<String, Object> suiXinFuResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
        result.setResultCode(suiXinFuResult.get("code").toString());
        if ("0000".equals(suiXinFuResult.get("code"))) {
            HashMap<String, Object> micropayResult = JSON.parseObject(suiXinFuResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            switch (micropayResult.get("tranSts").toString()) {
                case "SUCCESS":
                    result.setTradeState("SUCCESS");
                    result.setTradeType(dealPayType(micropayResult.get("payType").toString()));
                    result.setTimeEnd(micropayResult.get("payTime").toString());
                    int getAmount = (int) (Double.valueOf(micropayResult.get("oriTranAmt").toString()) * 100);
                    result.setTotalFee(getAmount);
                    result.setOutTradeNo(micropayResult.get("ordNo").toString());
                    break;
                case "FAIL":
                    result.setTradeState("PAYERROR");
                    break;
                case "PAYERROR":
                    result.setTradeState("PAYERROR");
                    break;
                case "CANCELED":
                    result.setTradeState("REVOKED");
                    break;
                case "CLOSED":
                    result.setTradeState("CLOSED");
                    break;
            }
        } else {
            result.setTradeState("PAYERROR");
        }
        return result;
    }


    public ALLPayQrCodeResult suixinfuRewardQRCode(StorePay storePay, Reward reward, PayTypeEnum typeEnum) throws Exception {
        return (ALLPayQrCodeResult) redisSyncLocker.idLock(reward.getId(), new ISyncExecutor() {
            @Override
            public Object execute(Object o) throws Exception {
                ALLPayQrCodeResult result = new ALLPayQrCodeResult();
                String url = "https://openapi.tianquetech.com/order/activeScan";
                SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
                reqBean.setOrgId(orgId);

                JSONObject reqData = new JSONObject();
                reqData.put("mno", storePay.getMchId()); //商户编号
                reqData.put("ordNo", reward.getId()); //商户订单号
                reqData.put("amt", String.valueOf(reward.getTotal())); //订单总金额
                if (typeEnum.equals(PayTypeEnum.PAY_WX_NATIVE)) {
                    reqData.put("payType", "WECHAT"); //支付渠道
                } else {
                    reqData.put("payType", "ALIPAY"); //支付渠道
                }
                reqData.put("subject", service.getRewardBody(reward)); //订单标题
                reqData.put("trmIp", "172.16.2.1");
                reqData.put("tradeSource", "01");
                reqData.put("notifyUrl", baseURL + "/v1/pay/suixinfu/callBack"); //回调地址
                reqBean.setReqData(reqData);
                String req = JSONObject.toJSONString(reqBean);
                System.out.println("req:" + req);
                HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
                //组装加密串
                String signContent = RSASignature.getOrderContent(reqMap);
                System.out.println("拼接后的参数：" + signContent);
                //sign
                String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
                System.out.println("============签名:" + sign);
                reqMap.put("sign", sign);

                String reqStr = JSON.toJSONString(reqMap);
                System.out.println("请求参数:" + reqMap);
                System.out.println("请求参数:" + reqStr);
                String resultJson = HttpUtils.connectPostUrl(url, reqStr);
                System.out.println("返回信息：" + resultJson);
                HashMap<String, Object> suiXinFuResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
                if ("0000".equals(suiXinFuResult.get("code"))) {
                    HashMap<String, Object> micropayResult = JSON.parseObject(suiXinFuResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            reward.setPayChannel(OrderPayChannel.SUI_XIN_FU);
                            reward.setStatus(OrderStatus.NOTSURE);
                            rewardDao.save(reward);
                        }
                    });
                    result.setStatus("0");
                    result.setResultCode("0");
                    result.setCodeImgURL(micropayResult.get("payUrl").toString());
                } else {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            reward.setPayChannel(OrderPayChannel.SUI_XIN_FU);
                            reward.setStatus(OrderStatus.CANCELED);
                            rewardDao.save(reward);
                        }
                    });
                    result.setStatus("1");
                    result.setResultCode("1");
                    result.setErrMsg(suiXinFuResult.get("msg").toString());
                }
                return result;
            }
        });
    }

    /**
     * 支付解冻
     *
     * @param
     * @param order
     * @return
     * @throws Exception
     */
    public ALLPayQrCodeResult suixinfuOrderQRCodeThaw(String mchId, LeaseProductOrder order) throws Exception {
        ALLPayQrCodeResult result = new ALLPayQrCodeResult();
        String url = "https://openapi.tianquetech.com/query/ledger/launchLedger";
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
        reqBean.setOrgId(orgId);
        JSONObject reqData = new JSONObject();
        reqData.put("mno", mchId); //商户编号
        reqData.put("ordNo", order.getOrderNum()); //商户订单号
        reqData.put("uuid", UuidUtil.getUuid()); //订单总金额
        reqData.put("ledgerAccountFlag", "02");
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        //组装加密串
        String signContent = RSASignature.getOrderContent(reqMap);
        //sign
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);
        String reqStr = JSON.toJSONString(reqMap);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        log.info("请求单号{},请求参数{},返回结果{}", order.getId(), reqMap, resultJson);
        return result;
    }


    public boolean dealLeaseProductInventory(LeaseProduct leaseProduct , String numName, LeaseProductOrder order) throws Exception {
        boolean judge = false;
        if (leaseProduct != null) {
            final int left = leaseProduct.getTotalCount() - leaseProduct.getSalesCount() - 1;
            log.info("订单号{}, 开始订单{}, 商品{}, 判断结果{}", order.getOrderNum(), order, leaseProduct, left);
            if (left < 0) {
                StorePay storePay = storePayDao.findByStoreIdAndStartEnabled(leaseProduct.getStoreId(), true);
                log.info("订单号{},开始订单{},商品{},查询出来的支付参数{}", order.getOrderNum(), order, leaseProduct, storePay);
                if (storePay != null) {
                    order.setStatus(OrderStatus.REFUNDED);
                    order.setRefundTime(new Date());
                    order.setRefundOrderNum("REF" + order.getOrderNum());
                    order.setRefundAmount(order.getTotalAmount());
                    if (order.getTotalAmount() > 0) {
                        suixinfuRefund(order.getRefundOrderNum(), storePay.getMchId(), order.getTotalAmount(), order.getOrderNum());
                    }
                }
            } else {
                leaseProduct.setTotalSalesCount(leaseProduct.getTotalSalesCount() + 1);
                if (null == leaseProduct.getNumName()) {
                    List<String> numNames = new ArrayList<>();
                    numNames.add(numName);
                    leaseProduct.setNumName(numNames);
                } else {
                    leaseProduct.getNumName().add(numName);
                }
                leaseProduct.setSalesCount(leaseProduct.getNumName().size());
                leaseProduct.setUpdateTime(new Date());
                leaseProductService.save(leaseProduct);
                judge = true;
            }
        }
        log.info("订单号{}, 结束订单{}, 商品{}", order.getOrderNum(), order, leaseProduct);
        return judge;
    }


    public ALLPayQrCodeResult suixinfuOrderQRCodeFrozen(StorePay storePay, LeaseProductOrder order) throws Exception {
        return (ALLPayQrCodeResult) redisSyncLocker.idLock(order.getOrderNum(), new ISyncExecutor() {
            @Override
            public Object execute(Object o) throws Exception {
                ALLPayQrCodeResult result = new ALLPayQrCodeResult();
                String url = "https://openapi.tianquetech.com/order/activePlusScan";
                SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
                reqBean.setOrgId(orgId);
                JSONObject reqData = new JSONObject();
                reqData.put("mno", storePay.getMchId()); //商户编号
                reqData.put("ordNo", order.getOrderNum()); //商户订单号
                reqData.put("amt", String.valueOf(order.getTotalAmount())); //订单总金额
                reqData.put("subject", order.getProductName() ); //订单标题
                reqData.put("ledgerAccountFlag", "07");
                reqData.put("ledgerAccountEffectTime", "30");
                reqData.put("trmIp", "172.16.2.1");
                reqData.put("tradeSource", "01");
                reqData.put("notifyUrl", baseURL + "/v1/pay/lease/suixinfu/callBack"); //回调地址
                reqBean.setReqData(reqData);
                String req = JSONObject.toJSONString(reqBean);
                System.out.println("req:" + req);
                HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
                //组装加密串
                String signContent = RSASignature.getOrderContent(reqMap);
                //sign
                String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
                System.out.println("============签名:" + sign);
                reqMap.put("sign", sign);
                String reqStr = JSON.toJSONString(reqMap);
                String resultJson = HttpUtils.connectPostUrl(url, reqStr);
                log.info("请求单号{},请求参数{},返回结果{}", order.getId(), reqMap, resultJson);
                HashMap<String, Object> suiXinFuResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
                if ("0000".equals(suiXinFuResult.get("code"))) {
                    HashMap<String, Object> micropayResult = JSON.parseObject(suiXinFuResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
                    order.setStatus(OrderStatus.NOTSURE);
                    leaseProductOrderDao.save(order);
                    result.setStatus("0");
                    result.setResultCode("0");
                    result.setCodeImgURL(micropayResult.get("payUrl").toString());
                } else {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setStatus(OrderStatus.CANCELED);
                            leaseProductOrderDao.save(order);
                        }
                    });
                    result.setStatus("1");
                    result.setResultCode("1");
                    result.setErrMsg(suiXinFuResult.get("msg").toString());
                }
                return result;
            }
        });
    }

    public ALLPayQrCodeResult suixinfuOrderQRCode(StorePay storePay, Order order, PayTypeEnum typeEnum) throws Exception {
        return (ALLPayQrCodeResult) redisSyncLocker.idLock(order.getId(), new ISyncExecutor() {
            @Override
            public Object execute(Object o) throws Exception {
                ALLPayQrCodeResult result = new ALLPayQrCodeResult();
                String url = "https://openapi.tianquetech.com/order/activePlusScan";
                SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
                reqBean.setOrgId(orgId);
                JSONObject reqData = new JSONObject();
                reqData.put("mno", storePay.getMchId()); //商户编号
                reqData.put("ordNo", order.getPayOrderId()); //商户订单号
                reqData.put("amt", String.valueOf(order.getAmount())); //订单总金额
                reqData.put("subject", service.getBody(order)); //订单标题
                reqData.put("trmIp", "172.16.2.1");
                reqData.put("tradeSource", "01");
                reqData.put("notifyUrl", baseURL + "/v1/pay/suixinfu/callBack"); //回调地址
                reqBean.setReqData(reqData);
                String req = JSONObject.toJSONString(reqBean);
                System.out.println("req:" + req);
                HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
                //组装加密串
                String signContent = RSASignature.getOrderContent(reqMap);
                //sign
                String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
                System.out.println("============签名:" + sign);
                reqMap.put("sign", sign);
                String reqStr = JSON.toJSONString(reqMap);
                String resultJson = HttpUtils.connectPostUrl(url, reqStr);
                log.info("请求单号{},请求参数{},返回结果{}", order.getId(), reqMap, resultJson);
                HashMap<String, Object> suiXinFuResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
                if ("0000".equals(suiXinFuResult.get("code"))) {
                    HashMap<String, Object> micropayResult = JSON.parseObject(suiXinFuResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setPayChannel(OrderPayChannel.SUI_XIN_FU);
                            order.setStatus(OrderStatus.NOTSURE);
                            orderDao.save(order);
                        }
                    });
                    result.setStatus("0");
                    result.setResultCode("0");
                    result.setCodeImgURL(micropayResult.get("payUrl").toString());
                } else {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setPayChannel(OrderPayChannel.SUI_XIN_FU);
                            order.setStatus(OrderStatus.CANCELED);
                            orderDao.save(order);
                        }
                    });
                    result.setStatus("1");
                    result.setResultCode("1");
                    result.setErrMsg(suiXinFuResult.get("msg").toString());
                }
                return result;
            }
        });
    }

    public ALLPayQrCodeResult suixinfuStockOrderQRCode(StorePay storePay, StockOrder order, PayTypeEnum typeEnum) throws Exception {
        return (ALLPayQrCodeResult) redisSyncLocker.idLock(order.getId(), new ISyncExecutor() {
            @Override
            public Object execute(Object o) throws Exception {
                ALLPayQrCodeResult result = new ALLPayQrCodeResult();
                String url = "https://openapi.tianquetech.com/order/activeScan";
                SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
                reqBean.setOrgId(orgId);

                JSONObject reqData = new JSONObject();
                reqData.put("mno", storePay.getMchId()); //商户编号
                reqData.put("ordNo", order.getId()); //商户订单号
                reqData.put("amt", String.valueOf(order.getAmount())); //订单总金额
                if (typeEnum.equals(PayTypeEnum.PAY_WX_NATIVE)) {
                    reqData.put("payType", "WECHAT"); //支付渠道
                } else {
                    reqData.put("payType", "ALIPAY"); //支付渠道
                }
                reqData.put("subject", getStockOrderBody(order)); //订单标题
                reqData.put("trmIp", "172.16.2.1");
                reqData.put("tradeSource", "01");
                reqData.put("notifyUrl", baseURL + "/v1/pay/sxf/stockCallBack"); //回调地址
                reqBean.setReqData(reqData);
                String req = JSONObject.toJSONString(reqBean);
                System.out.println("req:" + req);
                HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
                //组装加密串
                String signContent = RSASignature.getOrderContent(reqMap);
                System.out.println("拼接后的参数：" + signContent);
                //sign
                String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
                System.out.println("============签名:" + sign);
                reqMap.put("sign", sign);

                String reqStr = JSON.toJSONString(reqMap);
                System.out.println("请求参数:" + reqMap);
                System.out.println("请求参数:" + reqStr);
                String resultJson = HttpUtils.connectPostUrl(url, reqStr);
                System.out.println("返回信息：" + resultJson);
                HashMap<String, Object> suiXinFuResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
                if ("0000".equals(suiXinFuResult.get("code"))) {
                    HashMap<String, Object> micropayResult = JSON.parseObject(suiXinFuResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
                    result.setStatus("0");
                    result.setResultCode("0");
                    result.setCodeImgURL(micropayResult.get("payUrl").toString());
                } else {
                    result.setStatus("1");
                    result.setResultCode("1");
                    result.setErrMsg(suiXinFuResult.get("msg").toString());
                }
                return result;
            }
        });
    }

    private String getStockOrderBody(StockOrder reward) {
        StringBuffer stringBuffer = new StringBuffer();
        reward.getItems().forEach(e ->
                stringBuffer.append(e.getQty()).append("个").append(e.getProductName()));
        return Stringutil.cutStr(stringBuffer.toString(), 120);
    }

    public AllPayJsPayResult suixinfuJSPay(StorePay storePay, Order order, String openId) throws Exception {
        return (AllPayJsPayResult) redisSyncLocker.idLock(order.getId(), o -> {


            String url = "https://openapi.tianquetech.com/order/jsapiScan";
            AllPayJsPayResult result = new AllPayJsPayResult();
            SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
            reqBean.setOrgId(orgId);
            JSONObject reqData = new JSONObject();
            reqData.put("ordNo", order.getPayOrderId()); //商户订单号
            reqData.put("mno", storePay.getMchId()); //商户编号
            reqData.put("amt", String.valueOf(order.getAmount())); //订单总金额
            reqData.put("payType", "WECHAT"); //支付渠道
            reqData.put("payWay", "02"); //支付方式  02 公众号/服 务窗/js支付 03 小程序
            reqData.put("subject", service.getBody(order)); //订单标题
            reqData.put("tradeSource", "02"); //交易来源 01服务商，02收银台，03硬件
            reqData.put("trmIp", "172.16.2.1");
            reqData.put("customerIp", "125.69.15.61");
            reqData.put("userId", openId); //用户号 微信：openid； 支付宝：userid；银联：userid；微信&支付宝必传，银联js为非必传
            reqData.put("notifyUrl", baseURL + "/v1/pay/suixinfu/callBack"); //回调地址
            reqBean.setReqData(reqData);
            String req = JSONObject.toJSONString(reqBean);
            System.out.println("req:" + req);
            //此处不要改变reqData里面值的顺序用LinkedHashMap
            HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
            //组装加密串
            String signContent = RSASignature.getOrderContent(reqMap);
            System.out.println("拼接后的参数：" + signContent);
            //sign
            String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
            System.out.println("============签名:" + sign);
            reqMap.put("sign", sign);

            String reqStr = JSON.toJSONString(reqMap);
            System.out.println("请求参数:" + reqMap);
            System.out.println("请求参数:" + reqStr);
            String resultJson = HttpUtils.connectPostUrl(url, reqStr);

            System.out.println("返回信息：" + resultJson);
            //不要对reqData排序 所以用LinkedHashMap
            HashMap<String, Object> jsResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
            if (jsResult.get("code").equals("0000")) {
                HashMap<String, Object> micropayResult = JSON.parseObject(jsResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
                // 更新订单状态到支付中，防止其被更新
                if (micropayResult.get("bizCode").equals("0000")) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setPayChannel(OrderPayChannel.SUI_XIN_FU);
                            order.setStatus(OrderStatus.NOTSURE);
                            orderDao.save(order);
                            log.info("门店{}, 订单号{}, 操作{}", order.getStoreId(), order.getId(), "进入消息队列");
                            aliyunMNSSend.sendClint(order.getId());
                        }
                    });
                    result.setPayInfo(deal(micropayResult));
                    result.setResultCode("0");
                    result.setStatus("0");
                } else {
                    result.setResultCode("1");
                    result.setStatus("1");
                }
            }
            return result;
        });
    }


    public String deal(HashMap res) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appId", res.get("payAppId"));
        jsonObject.put("callback_url", "https://admin.huoxingy.com/static/sucPay/index.html");
        jsonObject.put("nonceStr", res.get("paynonceStr"));
        jsonObject.put("package", res.get("payPackage"));
        jsonObject.put("paySign", res.get("paySign"));
        jsonObject.put("signType", res.get("paySignType"));
        jsonObject.put("timeStamp", res.get("payTimeStamp"));
        jsonObject.put("status", "0");
        return jsonObject.toJSONString();
    }

    public SwiftPassRefundResult suixinfuRefund(String id, Order order, StorePay storePay) throws Exception {
        String url = "https://openapi.tianquetech.com/order/refund";
        SwiftPassRefundResult result = new SwiftPassRefundResult();
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
        reqBean.setOrgId(orgId);
        JSONObject reqData = new JSONObject();

        //业务参数
        reqData.put("ordNo", id); //商户订单号
        reqData.put("mno", storePay.getMchId()); //商户编号
        //下面三个至少传一个
        reqData.put("origOrderNo", order.getPayOrderId()); //原商户订单号

        reqData.put("amt", String.valueOf(order.getAmount())); //退款金额
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        String signContent = RSASignature.getOrderContent(reqMap);
        System.out.println("拼接后的参数：" + signContent);
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);

        String reqStr = JSON.toJSONString(reqMap);
        System.out.println("请求参数:" + reqMap);
        System.out.println("请求参数:" + reqStr);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        HashMap<String, Object> refundResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
        System.out.println("返回结果:" + refundResult);
        if (refundResult.get("code").equals("0000")) {
            HashMap<String, Object> dataResult = JSON.parseObject(refundResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (dataResult.get("bizCode").equals("0000") || dataResult.get("bizCode").equals("2002")) {
                result.setResultCode("0");
                result.setStatus("0");
                result.setRefundId(order.getId());
                result.setRefundFee((int) (order.getAmount() * 100));
            } else {
                result.setResultCode("1");
                result.setStatus("1");
                result.setErrMsg(dataResult.get("bizMsg").toString());
            }
        } else {
            result.setResultCode("1");
            result.setStatus("1");
            result.setErrMsg(refundResult.get("msg").toString());
        }
        return result;
    }



    public static SwiftPassRefundResult suixinfuRefundTesttete(String orderNum, String mchId, double amount, String oriNum) throws Exception {
        String privateKey1 = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALSudzxTPNFRY8ql\n" +
                "xf2BCgCpfLq7POr3QVMpeXHhYu52toTx3FrRv82zTOiRY/PpiYIrxkpHYsv0ihG8\n" +
                "kV+Zm7xQ02VGhqo9wJaM0Oaw45B0rw8YjX7UhSxOimlB0/rqTV7nMWmMisfBrZPS\n" +
                "LCKPub83vOw1trjH7Ur4gAd+AiL1AgMBAAECgYAIzNaR4Zv8tfIeVKSoDDjof1jL\n" +
                "34LADvrnigWYPloLM00AfKc25TBqXGlKiopLvvwrkuY9h+yP8oEnDAAon9qt5Gwh\n" +
                "RvYZoztTI8k4UQY6O32Wr4Ic+SzKHBFW7YFpp5iKIdniOL1aBrSfxobJRTzu/1ZF\n" +
                "7+/zfLmMVW/hJ1GCoQJBAN29e5h5I4E9LDovRibS64RHbDQfn/TfaKLxuy+qrJuI\n" +
                "FHD7e4bqtMkSv50T7TzgGMOzWwHmiJIi7GBOBEKQGB8CQQDQmPwJ2iZjkvHFxTpY\n" +
                "Iv1Xt6mKimIjhCMzVv8Bc8yfb9GmAkZaWerdxANu9Et0/86IJV/xQXpC3D/hABSe\n" +
                "rjJrAkBpl/dIl79xpxjtqF+G04B2YLDFbZ31tYIVvnm+bE+ATWA2oXuktxZafoQj\n" +
                "ID8kcy832qxnDkpRFTJtdhmPPSFPAkEAxV5K8yN2uTZbDm5rouMQZEPB5fTDoKkx\n" +
                "CS2iQISJsr2BVxrF6E01vbjuKrh5AO3dQ9JhMgtrHAH7au/BktZtmwJBANJWWsj0\n" +
                "17wCumql7m8ZMytPPKNzTZLrihj+LqQGg35AYA9cD++FqEQV/gWzNoOHPJ6XTdOL\n" +
                "xmgv5G+x8u32mns=";
        String url = "https://openapi.tianquetech.com/order/refund";
        SwiftPassRefundResult result = new SwiftPassRefundResult();
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
        reqBean.setOrgId("86146578");
        JSONObject reqData = new JSONObject();
        //业务参数
        reqData.put("ordNo", orderNum); //商户订单号
        reqData.put("mno", mchId); //商户编号
        //下面三个至少传一个
        reqData.put("origOrderNo", oriNum); //原商户订单号

        reqData.put("amt", String.valueOf(String.valueOf(BigDecimal.valueOf(amount).setScale(2, RoundingMode.HALF_UP)))); //退款金额
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        String signContent = RSASignature.getOrderContent(reqMap);
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey1));
        reqMap.put("sign", sign);
        String reqStr = JSON.toJSONString(reqMap);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        HashMap<String, Object> refundResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
        log.info("订单号{},请求参数{},退款返回结果{}", oriNum, reqStr, refundResult);
        if (refundResult.get("code").equals("0000")) {
            HashMap<String, Object> dataResult = JSON.parseObject(refundResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (dataResult.get("bizCode").equals("0000") || dataResult.get("bizCode").equals("2002")) {
                result.setResultCode("0");
                result.setStatus("0");
                result.setRefundId(orderNum);
                result.setRefundFee((int) (amount * 100));
            } else {
                result.setResultCode("1");
                result.setStatus("1");
                result.setErrMsg(dataResult.get("bizMsg").toString());
            }
        } else {
            result.setResultCode("1");
            result.setStatus("1");
            result.setErrMsg(refundResult.get("msg").toString());
        }
        return result;
    }
    public SwiftPassRefundResult suixinfuRefund(String orderNum, String mchId, double amount, String oriNum) throws Exception {
        String url = "https://openapi.tianquetech.com/order/refund";
        SwiftPassRefundResult result = new SwiftPassRefundResult();
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
        reqBean.setOrgId(orgId);
        JSONObject reqData = new JSONObject();
        //业务参数
        reqData.put("ordNo", orderNum); //商户订单号
        reqData.put("mno", mchId); //商户编号
        //下面三个至少传一个
        reqData.put("origOrderNo", oriNum); //原商户订单号

        reqData.put("amt", String.valueOf(BigDecimal.valueOf(amount).setScale(2, RoundingMode.HALF_UP))); //退款金额
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        String signContent = RSASignature.getOrderContent(reqMap);
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        reqMap.put("sign", sign);
        String reqStr = JSON.toJSONString(reqMap);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        HashMap<String, Object> refundResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
        log.info("订单号{},请求参数{},退款返回结果{}", oriNum, reqStr, refundResult);
        if (refundResult.get("code").equals("0000")) {
            HashMap<String, Object> dataResult = JSON.parseObject(refundResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (dataResult.get("bizCode").equals("0000") || dataResult.get("bizCode").equals("2002")) {
                result.setResultCode("0");
                result.setStatus("0");
                result.setRefundId(orderNum);
                result.setRefundFee((int) (amount * 100));
            } else {
                result.setResultCode("1");
                result.setStatus("1");
                result.setErrMsg(dataResult.get("bizMsg").toString());
            }
        } else {
            result.setResultCode("1");
            result.setStatus("1");
            result.setErrMsg(refundResult.get("msg").toString());
        }
        return result;
    }

    public SwiftPassRefundResult suixinfuRefundTest(String id, Order order, StorePay storePay, String amount) throws Exception {
        String url = "https://openapi.tianquetech.com/order/refund";
        SwiftPassRefundResult result = new SwiftPassRefundResult();
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
        reqBean.setOrgId(orgId);
        JSONObject reqData = new JSONObject();

        //业务参数
        reqData.put("ordNo", id); //商户订单号
        reqData.put("mno", storePay.getMchId()); //商户编号
        //下面三个至少传一个
        reqData.put("origOrderNo", order.getPayOrderId()); //原商户订单号

        reqData.put("amt", amount); //退款金额
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        String signContent = RSASignature.getOrderContent(reqMap);
        System.out.println("拼接后的参数：" + signContent);
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);

        String reqStr = JSON.toJSONString(reqMap);
        System.out.println("请求参数:" + reqMap);
        System.out.println("请求参数:" + reqStr);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        HashMap<String, Object> refundResult = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
        System.out.println("返回结果:" + refundResult);
        if (refundResult.get("code").equals("0000")) {
            HashMap<String, Object> dataResult = JSON.parseObject(refundResult.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (dataResult.get("bizCode").equals("0000") || dataResult.get("bizCode").equals("2002")) {
                result.setResultCode("0");
                result.setStatus("0");
                result.setRefundId(order.getId());
                result.setRefundFee((int) (order.getAmount() * 100));
            } else {
                result.setResultCode("1");
                result.setStatus("1");
                result.setErrMsg(dataResult.get("bizMsg").toString());
            }
        } else {
            result.setResultCode("1");
            result.setStatus("1");
            result.setErrMsg(refundResult.get("msg").toString());
        }
        return result;
    }

    public AllPayRefundQueryResult suixingfuRefundQuery(StorePay storePay, Order order) throws Exception {
        String url = "https://openapi.tianquetech.com/query/refundQuery";
        AllPayRefundQueryResult refundResult = new AllPayRefundQueryResult();
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
        reqBean.setOrgId(orgId);
        JSONObject reqData = new JSONObject();
        //业务参数
        reqData.put("mno", storePay.getMchId()); //商户编号
        //下面两个至少传一个
        //兼容未发版之前的订单。
        reqData.put("ordNo", StringUtils.isNotBlank(order.getPayOrderId()) ? order.getPayOrderId() : order.getId()); //商户订单号
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        //此处不要改变reqData里面值的顺序用LinkedHashMap
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        //组装加密串
        String signContent = RSASignature.getOrderContent(reqMap);
        System.out.println("拼接后的参数：" + signContent);
        //sign
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);

        String reqStr = JSON.toJSONString(reqMap);
        System.out.println("请求参数:" + reqMap);
        System.out.println("请求参数:" + reqStr);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        System.out.println("返回信息：" + resultJson);
        //不要对reqData排序 所以用LinkedHashMap
        HashMap<String, Object> result = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
        if (result.get("code").equals("0000")) {
            HashMap<String, Object> refundQueryResult = JSON.parseObject(result.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (refundQueryResult.get("bizCode").equals("0000")) {
                switch (refundQueryResult.get("tranSts").toString()) {
                    case "REFUNDSUC":
                        refundResult.setStatus("0");
                        refundResult.setResultCode("0");
                        refundResult.setRefundTime(refundQueryResult.get("payTime").toString());
                        refundResult.setRefundId(refundQueryResult.get("ordNo").toString());
                        int getAmount = (int) (Double.valueOf(refundQueryResult.get("refundAmount").toString()) * 100);
                        refundResult.setRefundFee(getAmount);
                        refundResult.setRefundStatus("SUCCESS");
                        break;
                    case "REFUNDING":
                        refundResult.setStatus("0");
                        refundResult.setResultCode("0");
                        refundResult.setRefundStatus("PROCESSING");
                }
            }

        }

        return refundResult;
    }

    public AllPayRefundQueryResult handRefundQuery(StorePay storePay, String id) throws Exception {
        String url = "https://openapi.tianquetech.com/query/refundQuery";
        AllPayRefundQueryResult refundResult = new AllPayRefundQueryResult();
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
        reqBean.setOrgId(orgId);
        JSONObject reqData = new JSONObject();
        //业务参数
        reqData.put("mno", storePay.getMchId()); //商户编号
        //下面两个至少传一个
        reqData.put("ordNo", id); //商户订单号
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        //此处不要改变reqData里面值的顺序用LinkedHashMap
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        //组装加密串
        String signContent = RSASignature.getOrderContent(reqMap);
        System.out.println("拼接后的参数：" + signContent);
        //sign
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);

        String reqStr = JSON.toJSONString(reqMap);
        System.out.println("请求参数:" + reqMap);
        System.out.println("请求参数:" + reqStr);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        System.out.println("返回信息：" + resultJson);
        //不要对reqData排序 所以用LinkedHashMap
        HashMap<String, Object> result = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
        if (result.get("code").equals("0000")) {
            HashMap<String, Object> refundQueryResult = JSON.parseObject(result.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (refundQueryResult.get("bizCode").equals("0000")) {
                switch (refundQueryResult.get("tranSts").toString()) {
                    case "REFUNDSUC":
                        refundResult.setStatus("0");
                        refundResult.setResultCode("0");
                        refundResult.setRefundTime(refundQueryResult.get("payTime").toString());
                        refundResult.setRefundId(refundQueryResult.get("ordNo").toString());
                        int getAmount = (int) (Double.valueOf(refundQueryResult.get("refundAmount").toString()) * 100);
                        refundResult.setRefundFee(getAmount);
                        refundResult.setRefundStatus("SUCCESS");
                        break;
                    case "REFUNDING":
                        refundResult.setStatus("0");
                        refundResult.setResultCode("0");
                        refundResult.setRefundStatus("PROCESSING");
                }
            }

        }

        return refundResult;
    }


    public void suixinfuCallbackForThirdPartyRefundSuccess(AllPayRefundQueryResult result) {
        log.debug("Step in callback for third party refund success...");
        Payment payment = paymentDao.findOne(result.getRefundId());
        payment.setStatus(PaymentStatus.SUCCESS);
        payment.setSuccess(true);

        Date paymentTime = MyDateUtils.getDateFormatDd(result.getRefundTime(), "yyyyMMddHHmmss");
        payment.setCreateTime(paymentTime);

        Order refundOrder = orderDao.findOne(payment.getOrderId());
        refundOrder.setPayChannel(OrderPayChannel.SUI_XIN_FU);
        refundOrder.setStatus(OrderStatus.REFUNDED);
        refundOrder.setPaymentTime(paymentTime);

        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                orderDao.save(refundOrder);
                paymentDao.save(payment);
            }
        });

        try {
            service.postRefundSuccess(refundOrder);
        } catch (Exception e1) {
            log.info(e1.toString());
        }
    }

    public void suixinfuCallbackForThirdPartyRefundFail(AllPayRefundQueryResult result) {
        Order refundOrder = orderDao.findByIdOrPayOrderIdAndAmountGreaterThan(result.getOutRefundNo(), result.getOutRefundNo(), 0);
        refundOrder.setPayChannel(OrderPayChannel.SUI_XIN_FU);
        refundOrder.setStatus(OrderStatus.INIT);

        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                orderDao.save(refundOrder);
            }
        });
    }


    public void suixinfuCallbackForMicroPaymentFailed(String orderId, AllPayBaseQueryResult queryResult) throws Exception {
        String orgOrderId = queryResult.getOutTradeNo();
        if (queryResult.getOutTradeNo().length() > 32) {
            orgOrderId = orderId.substring(4);
        }
        Order order = orderDao.findByIdOrPayOrderIdAndAmountGreaterThan(orgOrderId, queryResult.getOutTradeNo(), 0);
        Reward reward = rewardDao.findOne(orderId);
        if (reward != null) {
            if (reward.getStatus().equals(OrderStatus.INIT)) {
                // 说明已经处理过支付失败的情况
                return;
            } else {
                // 支付失败后订单返回未结算状态，允许再次结算
                reward.setStatus(OrderStatus.INIT);
                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        rewardDao.save(reward);
                    }
                });
            }
        } else {
            if (order.getStatus().equals(OrderStatus.CANCELED)) {
                // 说明已经处理过支付失败的情况
                return;
            } else {
                // 支付失败后订单返回未结算状态，允许再次结算
                order.setStatus(OrderStatus.CANCELED);

                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        orderDao.save(order);
                    }
                });
            }
        }
    }

    public AllPayReverseResult cancelPay(String orderId) throws Exception {
        String orgOrderId = orderId;
        if (orderId.length() > 32) {
            orgOrderId = orderId.substring(4);
        }
        Order order = orderDao.findByIdOrPayOrderIdAndAmountGreaterThan(orgOrderId, orderId, 0);
        Reward reward = rewardDao.findOne(orderId);
        AllPayReverseResult result = new AllPayReverseResult();
        log.info("门店{}, 订单号{}, 操作{}, 操作内容{}, reward:{}", order.getStoreId(), order.getId(), "取消订单开始", order, reward);

        if (reward != null) {
            reward.setPayChannel(OrderPayChannel.SUI_XIN_FU);
            if (reward.getStatus().equals(OrderStatus.CANCELED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "该笔支付已经被取消");
                result.setStatus("0");
                result.setResultCode("0");
                return result;
            } else if (reward.getStatus().equals(OrderStatus.UNFINISHED) || reward.getStatus().equals(OrderStatus.FINISHED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "已经成功支付，取消支付操作被中止。");
                result.setStatus("0");
                result.setResultCode("0");
                return result;
            } else {
                StorePay store = storePayDao.findByStoreIdAndStartEnabled("574b59ef-b19c-11e7-9233-37891743d141", true);
                AllPayBaseQueryResult paymentResult = suiXinFuQuery(reward.getId(), store.getMchId());
                if (paymentResult.isSuccess()) {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "已经成功支付，取消支付操作被中止(火星云)。");
                    result.setStatus("0");
                    result.setResultCode("0");
                    return result;
                }
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "调用关闭订单接口");
                result = reversePayment(reward.getId(), store);
                if (result.isSuccess()) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            reward.setStatus(OrderStatus.CANCELED);
                            rewardDao.save(reward);
                        }
                    });
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "撤消成功");
                    return result;
                } else {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "调用关闭订单接口失败：" + result.getErrMsg());
                    throw new RuntimeException(result.getErrMsg());
                }
            }
        } else {
            if (order.getStatus().equals(OrderStatus.CANCELED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "支付已经被取消，请到订单列表查询确认");
                result.setStatus("0");
                result.setResultCode("0");
                return result;
            } else if (order.getStatus().equals(OrderStatus.UNFINISHED) || order.getStatus().equals(OrderStatus.FINISHED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                result.setStatus("0");
                result.setResultCode("0");
                return result;
            } else {
                StorePay store = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);
                AllPayBaseQueryResult paymentResult = suiXinFuQuery(order.getId(), store.getMchId());
                order.setPayChannel(OrderPayChannel.SUI_XIN_FU);
                if (paymentResult.isSuccess()) {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                    result.setStatus("0");
                    result.setResultCode("0");
                    return result;
                }
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "优先调用撤消订单接口");
                // 先调用撤销订单接口
                result = reversePayment(order.getId(), store);
                if (result.isSuccess()) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setStatus(OrderStatus.CANCELED);
                            orderDao.save(order);
                        }
                    });
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "撤消成功");
                    return result;
                } else {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "调用关闭订单接口失败：" + result.getErrMsg());
                    throw new RuntimeException("取消支付失败，请稍后再试");
                }
            }
        }
    }


    public AllPayReverseResult reversePayment(String orderId, StorePay storePay) throws Exception {
        String url = "https://openapi.tianquetech.com/query/cancel";
        AllPayReverseResult refundResult = new AllPayReverseResult();
        SuiXinFuBasePayReq<JSONObject> reqBean = new SuiXinFuBasePayReq<JSONObject>();
        reqBean.setOrgId(orgId);
        JSONObject reqData = new JSONObject();
        //业务参数
        reqData.put("mno", storePay.getMchId()); //商户编号
        //下面两个至少传一个
        reqData.put("origOrderNo", orderId); //商户订单号
        reqBean.setReqData(reqData);
        String req = JSONObject.toJSONString(reqBean);
        System.out.println("req:" + req);
        //此处不要改变reqData里面值的顺序用LinkedHashMap
        HashMap reqMap = JSON.parseObject(req, LinkedHashMap.class, Feature.OrderedField);
        //组装加密串
        String signContent = RSASignature.getOrderContent(reqMap);
        System.out.println("拼接后的参数：" + signContent);
        //sign
        String sign = RSASignature.encryptBASE64(RSASignature.sign(signContent, privateKey));
        System.out.println("============签名:" + sign);
        reqMap.put("sign", sign);

        String reqStr = JSON.toJSONString(reqMap);
        System.out.println("请求参数:" + reqMap);
        System.out.println("请求参数:" + reqStr);
        String resultJson = HttpUtils.connectPostUrl(url, reqStr);
        System.out.println("返回信息：" + resultJson);
        //不要对reqData排序 所以用LinkedHashMap
        HashMap<String, Object> result = JSON.parseObject(resultJson, LinkedHashMap.class, Feature.OrderedField);
        if (result.get("code").equals("0000")) {
            HashMap<String, Object> refundQueryResult = JSON.parseObject(result.get("respData").toString(), LinkedHashMap.class, Feature.OrderedField);
            if (refundQueryResult.get("bizCode").equals("0000")) {
                refundResult.setStatus("0");
                refundResult.setResultCode("0");
            } else {
                refundResult.setStatus("1");
                refundResult.setResultCode("1");
                refundResult.setErrMsg(refundQueryResult.get("bizMsg").toString());
            }
        } else {
            refundResult.setStatus("1");
            refundResult.setResultCode("1");
            refundResult.setErrMsg(result.get("msg").toString());
        }
        return refundResult;
    }


    public void suixinfuCallbackForMicroPaymentSuccess(AllPayBaseQueryResult queryResult) throws Exception {
        String orgOrderId = queryResult.getOutTradeNo();
        if (queryResult.getOutTradeNo().length() > 32) {
            orgOrderId = queryResult.getOutTradeNo().substring(4);
        }

        Order order = orderDao.findByIdOrPayOrderIdAndAmountGreaterThan(orgOrderId, queryResult.getOutTradeNo(), 0);
        Reward reward = rewardDao.findOne(queryResult.getOutTradeNo());
        if (reward != null) {
            reward.setPayChannel(OrderPayChannel.SUI_XIN_FU);
            if (reward.getStatus().equals(OrderStatus.FINISHED) || reward.getStatus().equals(OrderStatus.UNFINISHED)) {
                // 已经处理过支付成功事件
                return;
            }
            reward.setPaymentTime(MyDateUtils.getDateFormatDd(queryResult.getTimeEnd(), "yyyyMMddHHmmss"));
            reward.setChannel(queryResult.getTradeType());
            reward.setStatus(OrderStatus.FINISHED);
            AccountBalance accountBalance = accountBalanceDao.findByStoreId(reward.getStoreId());
            log.info("accountBalance" + accountBalance);
            if (accountBalance == null) {
                accountBalance = new AccountBalance(queryResult.getTotalFee(), reward.getStoreId());
            } else {
                accountBalance.setAmount(accountBalance.getAmount() + queryResult.getTotalFee());
            }
            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    rewardDao.save(reward);

                }
            });
            accountBalanceDao.save(accountBalance);
            aliyunMNSSend.sendClint(reward.getId());
        } else {
            if (order.getStatus().equals(OrderStatus.FINISHED) || order.getStatus().equals(OrderStatus.UNFINISHED)) {
                // 已经处理过支付成功事件
                return;
            }
            order.setPayChannel(OrderPayChannel.SUI_XIN_FU);
            Store store = storeDao.findOne(order.getStoreId());

            Payment payment = new Payment();
            payment.setId(UuidUtil.getUuid());
            payment.setOrderId(order.getId());
            payment.setStoreId(order.getStoreId());
            payment.setSuccess(queryResult.isSuccess());
            payment.setStatus(PaymentStatus.SUCCESS);
            Date paymentTime = MyDateUtils.getDateFormatDd(queryResult.getTimeEnd(), "yyyyMMddHHmmss");
            payment.setCreateTime(paymentTime);
            payment.setAmount(queryResult.getTotalFee() / 100.0);
            payment.setChannel(queryResult.getTradeType());


            if (OrderSource.POS == order.getSource()) {
                order.setStatus(OrderStatus.FINISHED);
            } else {
                order.setStatus(OrderStatus.UNFINISHED);
            }
            order.setPaymentTime(payment.getCreateTime());
            order.setPayId(payment.getId());
            order.setChannel(queryResult.getTradeType());

            // 订单与支付信息的更新在同一个事务中
            paymentDao.save(payment);
            orderDao.save(order);
            couponInstanceService.writeOffCouponInstanceByOrderId(order);
            service.postPaymentSuccess(order, store);
        }

    }


}
